package com.ceair.flight.refund.service.notification.impl;

import com.ceair.flight.refund.dto.external.BaseRes;
import com.ceair.flight.refund.dto.external.MultiRes;
import com.ceair.flight.refund.dto.external.RefundApply;
import com.ceair.flight.refund.dto.external.RefundTkt;
import com.ceair.flight.refund.location.dt.enums.ModuleConstants;
import com.ceair.flight.refund.location.dt.enums.RefundNotifyType;
import com.ceair.flight.refund.location.dt.enums.RefundReasonEnum;
import com.ceair.flight.refund.service.notification.INotification;
import com.ceair.flight.refund.service.notification.INotificationPointCut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author youguilin
 */
@Service("notificationAspect")
public class NotificationAspect implements INotificationPointCut {

    private static final Logger LOG = LoggerFactory.getLogger(NotificationAspect.class);
    @Resource(name = "refundSuccessNotification")
    private INotification refundApplyNotification;

    @Override
    public void notifyPax4Refund(Set<RefundApply> refundApplys, MultiRes refundResult) {
        try {
            for (RefundApply refundApply : refundApplys) {
                Map args = buildMapArg(refundApply);
                if (args == null) {
                    continue;
                }
                RefundTkt refundTkt = refundApply.getRefundTkt();
                String ticketNo = refundTkt.getTicketNo();
                BaseRes refundRes = refundResult.getRes(ticketNo);
                boolean isSuccess = refundRes.isSuccess();
                if (!isSuccess) {
                    LOG.warn("Ticket No {} refund failed, not going to send notification to customer", ticketNo);
                    continue;
                } else {
                    //risk check fail refund and user refuse pay refund, default not send notification
                    LOG.debug("Checking refund apply {} whether it is risk check fail refund and user refuse pay refund", refundApply.getId());
                    String status = refundApply.getStatus();
                    if (RefundReasonEnum.getByCode(status) == RefundReasonEnum.RISK_CHECK_FAILED
                            || RefundReasonEnum.getByCode(status) == RefundReasonEnum.USER_REFUSE_PAY) {
                        LOG.info("Refund apply {} is risk check fail or user refuse pay refund,which default not send notification", refundApply.getId());
                    }
                }
                args.put(ModuleConstants.REFUND_TICKET_STATUS_KEY, refundRes.isSuccess());
                LOG.info("Sending message to passenger {}, {}", refundTkt.getPaxId(), refundTkt.getPaxName());
                refundApplyNotification.notify4Apply(args);
            }
        } catch (Exception ex) {
            LOG.error("One or more notifications send failed", ex);
        }
    }

    private Map buildMapArg(RefundApply refundApply) {
        Map args = new HashMap();
        args.put(ModuleConstants.REFUND_APPLY_KEY, refundApply);
        args.put(ModuleConstants.REFUND_APPLY_ID_KEY, refundApply.getId());
        RefundTkt refundTkt = refundApply.getRefundTkt();
        args.put(ModuleConstants.BIG_ORDER_NO_KEY, refundTkt.getOrderNo());
        args.put(ModuleConstants.FLIGHT_ORDER_NO_KEY, refundTkt.getFlightOrderNo());
        args.put(ModuleConstants.TICKET_NO_KEY, refundTkt.getTicketNo());
        String notifyType = refundTkt.getNotifyPax();
        LOG.info("Passenger {}'s notification type is {}", refundTkt.getPaxName(), RefundNotifyType.getByCode(notifyType));
        if (RefundNotifyType.NOT == RefundNotifyType.getByCode(notifyType)) {
            LOG.warn("Skip send notification to passenger because the notify type is NO");
            return null;
        }
        args.put(ModuleConstants.NOTIFY_TYPE_KEY, notifyType);
        return args;
    }

}
